package com.lineage.server.datatables;

import com.lineage.DatabaseFactory;
import com.lineage.server.templates.L1Exp;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class ExpTable {
  private static final Log _log = LogFactory.getLog(ExpTable.class);
  
  public static int MAX_LEVEL = 0;
  
  public static long MAX_EXP = 0L;
  
  private static ExpTable _instance;
  
  private static final Map<Integer, L1Exp> _expList = new HashMap<>();
  
  public static ExpTable get() {
    if (_instance == null)
      _instance = new ExpTable(); 
    return _instance;
  }
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("SELECT * FROM `exp`");
      rs = pstm.executeQuery();
      while (rs.next()) {
        int level = rs.getInt("level");
        long exp = rs.getLong("exp");
        double expPenalty = rs.getDouble("expPenalty");
        if (level > MAX_LEVEL)
          MAX_LEVEL = level; 
        if (exp > MAX_EXP)
          MAX_EXP = exp; 
        L1Exp l1exp = new L1Exp();
        l1exp.set_level(level);
        l1exp.set_exp(exp);
        l1exp.set_expPenalty(expPenalty);
        _expList.put(new Integer(level), l1exp);
      } 
      _log.info("载入经验质设置资料数量: " + _expList.size() + "(" + timer.get() + "ms)");
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    MAX_LEVEL = MAX_LEVEL - 1;
  }
  
  public static long getExpByLevel(int level) {
    L1Exp l1exp = _expList.get(new Integer(level - 1));
    long exp = 0L;
    if (l1exp != null)
      exp = l1exp.get_exp(); 
    return exp;
  }
  
  public static long getNeedExpNextLevel(int level) {
    return getExpByLevel(level + 1) - getExpByLevel(level);
  }
  
  public static int getLevelByExp(long exp) {
    int level = 1;
    Iterator<Integer> iterator = _expList.keySet().iterator();
    while (iterator.hasNext()) {
      Integer integer = iterator.next();
      if (integer.intValue() == 0)
        continue; 
      L1Exp up = _expList.get(integer);
      L1Exp dn = _expList.get(Integer.valueOf(integer.intValue() - 1));
      long upe = up.get_exp();
      long dne = dn.get_exp();
      if (exp < dne || exp >= upe)
        continue; 
      level = integer.intValue();
    } 
    return Math.min(level, MAX_LEVEL);
  }
  
  public static int getExpPercentage(int level, long exp) {
    return (int)(100.0D * (exp - getExpByLevel(level)) / getNeedExpNextLevel(level));
  }
  
  public static double getPenaltyRate(int level, int levelmet) {
    L1Exp l1exp = _expList.get(new Integer(level));
    double expPenalty = 1.0D;
    if (l1exp != null)
      expPenalty = 1.0D / l1exp.get_expPenalty(); 
    return expPenalty;
  }
  
  public static double calcPercentageExp(int level, int percentage) {
    long needExp = getNeedExpNextLevel(level);
    double rate = percentage / 100.0D;
    return needExp * rate;
  }
  
  public static double getPenaltyRate(int level) {
    L1Exp l1exp = _expList.get(new Integer(level));
    double expPenalty = 1.0D;
    if (l1exp != null)
      expPenalty = 1.0D / l1exp.get_expPenalty(); 
    return expPenalty;
  }
}
